package com.bpmn.flow.behavior;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.RandomUtil;
import com.bpmn.common.constant.ApprovalModeConstants;
import com.bpmn.common.constant.BpmnModelConstants;
import com.bpmn.utils.TaskConfigUtils;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.UserTask;
import org.flowable.common.engine.impl.el.ExpressionManager;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.flowable.task.service.TaskService;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;

/**
 * 自定义的【单个】流程任务的 assignee 负责人的分配
 * 第一步，基于分配规则，计算出分配任务的【单个】候选人。如果找不到，则直接报业务异常，不继续执行后续的流程；
 * 第二步，随机选择一个候选人，则选择作为 assignee 负责人。
 *
 * @author rain
 */
@Setter
@Slf4j
public class BpmUserTaskActivityBehavior extends UserTaskActivityBehavior {

    private BpmTaskCandidateInvoker taskCandidateInvoker;

    private TaskConfigUtils.TaskConfig taskConfig;

    public BpmUserTaskActivityBehavior(UserTask userTask) {
        super(userTask);
        taskConfig = TaskConfigUtils.getTaskConfig(userTask);
        if (taskConfig != null) {
            userTask.setAssignee(null);
            //会签节点设置变量
            if (taskConfig.isMultiInstanceNode()) {
                userTask.setAssignee("${" + BpmnModelConstants.MULTI_INSTANCE_ASSIGNEES_VAR + "}");
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    protected void handleAssignments(TaskService taskService, String assignee, String owner,
                                     List<String> candidateUsers, List<String> candidateGroups, TaskEntity task, ExpressionManager expressionManager,
                                     DelegateExecution execution, ProcessEngineConfigurationImpl processEngineConfiguration) {
        String approvalMode = taskConfig.getApprovalMode();
        // 根据审批模式处理任务分配
        if (ApprovalModeConstants.EXTERNAL.equals(approvalMode)) {
            // 外部系统分配模式
            Set<String> candidateUserIds = taskCandidateInvoker.calculateUsersByTask(execution);
            if (CollUtil.isNotEmpty(candidateUserIds)) {
                int index = RandomUtil.randomInt(candidateUserIds.size());
                assignee = CollUtil.get(candidateUserIds, index);
            }
        }
        super.handleAssignments(taskService, assignee, owner, candidateUsers, candidateGroups, task, expressionManager, execution, processEngineConfiguration);
    }

}